#pragma once
#include "Sem.hpp"
#include "Mutex.hpp"
#include <iostream>
#include <pthread.h>
#include <vector>
#include <unistd.h>
using namespace Sem_Modle;
using namespace Mutex_Model;
static const int gdefault = 5;
template <class T>
class Ring_Queue
{
public:
    Ring_Queue()
        : _cap(gdefault), _p_step(0), _c_step(0), _blank_sem(_cap), _data_sem(0)
    {
        _rq.resize(_cap); // 初始化vector大小！
    }

    void Equeue(const T &in)
    {
        {
            // 申请资源
            _blank_sem.P();
            // 加锁
            Mutex_Gurda P_Lock(&_p_mutex);
            // 生产数据
            _rq[_p_step++] = in;
            std::cout << "生产的数据是: " << in << "下标是: " << _p_step << std::endl;
            // 维护_p_step 防止越界
            _p_step %= _cap;
        }
        // 释放资源(释放消费者资源)
        _data_sem.V();
    }

    T Pop()
    {
        T data;
        // 申请资源
        _data_sem.P();
        {
            // 加锁
            Mutex_Gurda C_Lock(&_c_mutex);
            // 消费数据
            data = _rq[_c_step];
            std::cout << "消费的数据是: " << data << "下标是: " << _c_step << std::endl;
            _c_step++;
            // 维护_c_step 防止越界
            _c_step %= _cap;
        }
        // 释放资源(释放生产者资源)
        _blank_sem.V();
        return data;
    }
    ~Ring_Queue()
    {
    }

private:
    std::vector<T> _rq; // 环形队列
    int _cap;           // 环形队列容量
    int _p_step;        // 生产者步长
    int _c_step;        // 消费者步长
    Sem _blank_sem;     // 生产者信号量
    Sem _data_sem;      // 消费者信号量
    Mutex _p_mutex;     // 生产者锁
    Mutex _c_mutex;     // 消费者锁
};